Skip to content

Fix: DeployComponents leaves __BUN_PATH__ unsubstituted in the pulse launchd plist (EX_CONFIG)#1436

Closed
rrittich wants to merge 1 commit into
danielmiessler:mainfrom
rrittich:fix/deploycomponents-bun-path-plist
Closed

Fix: DeployComponents leaves __BUN_PATH__ unsubstituted in the pulse launchd plist (EX_CONFIG)#1436
rrittich wants to merge 1 commit into
danielmiessler:mainfrom
rrittich:fix/deploycomponents-bun-path-plist

Conversation

@rrittich

@rrittich rrittich commented Jul 6, 2026

Copy link
Copy Markdown

Problem

The pulse component in DeployComponents.ts materializes the launchd plist from the template com.lifeos.pulse.plist, which contains two placeholders — __HOME__ and __BUN_PATH__. But materialization substitutes only __HOME__:

const materialized = readFileSync(plistSrc, "utf-8").replaceAll("__HOME__", ctx.home);

__BUN_PATH__ is left literal, so the written plist is:

<key>ProgramArguments</key>
<array>
    <string>__BUN_PATH__</string>
    <string>run</string>
    <string>pulse.ts</string>
</array>

launchd can't exec a program literally named __BUN_PATH__, so the service fails to start and launchctl print gui/<uid>/com.lifeos.pulse reports last exit code = 78 (EX_CONFIG). bun Tools/DeployComponents.ts --apply --components pulse returns applied: true but the healthz probe returns 000 — the daemon never runs under launchd, even though it runs fine when invoked directly (bun run pulse.ts).

Fix

Also substitute __BUN_PATH__, using the bun binary running the deploy (process.execPath):

const materialized = readFileSync(plistSrc, "utf-8")
  .replaceAll("__HOME__", ctx.home)
  .replaceAll("__BUN_PATH__", process.execPath);

Verification

  • Before: managed service exits EX_CONFIG; healthz → 000; dashboard unreachable.
  • After (plist with the substitution): launchctl print shows state = running, last exit code = (never exited); healthz → 200; dashboard 200. Same daemon, now execs correctly under launchd.

Single line, single file. (The dry-run action message near L151 also only names __HOME__; happy to update it to mention __BUN_PATH__ for accuracy if desired.)

The pulse component materializes com.lifeos.pulse.plist but only replaces
__HOME__, leaving __BUN_PATH__ literal. launchd then tries to exec a program
named '__BUN_PATH__' and the service dies with EX_CONFIG (78) / healthz 000,
even though 'bun run pulse.ts' works directly. Substitute __BUN_PATH__ with
process.execPath so the managed service actually starts.
@danielmiessler

Copy link
Copy Markdown
Owner

Thanks a lot for this, @rrittich — really appreciate you flagging it and taking the time to write the fix.

When I went back through the current source, this turns out to already be handled: the BUN_PATH plist substitution is already in current source (via ctx.bun with a resolution fallback), so the EX_CONFIG bug can't occur — thanks for catching the same class of issue. The system has moved a fair bit since you opened this (the PAI → LifeOS rename and a few subsystem rewrites), so the gap you spotted has since been closed independently.

Going to close this one out on that basis — but genuinely grateful for the contribution. 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants